package cn.huhaoran.yaoyaolingxian.util;

import com.intellij.notification.Notification;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.intellij.openapi.actionSystem.AnActionEvent;

import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.ui.awt.RelativePoint;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;

import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.*;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author huhaoran
 * @description: 遥遥领先工具类
 * @date 2024/7/14
 */
public class YaoYaoLingXianUtils {

    public static void generatePageFile(AnActionEvent e, HashMap<String, Object> data, ClassLoader cl) {
       /* ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(cl);*/
        String filePath = (String) data.remove("filePath");
        String jsonPath = (String) data.remove("jsonPath");
        String enumPath = (String) data.remove("enumPath");
        String pageName = (String) data.get("pageName");
        String pageNameCN = (String) data.get("pageNameCN");
        String enumIndex = (String) data.get("enumIndex");
        VelocityContext context = new VelocityContext();
        data.forEach(context::put);

        String templatePageName = "${pageName}Page.ets";
        String tagePageName = templatePageName.replace("${pageName}", pageName);
        String pagePath = filePath + File.separator + tagePageName;

        String templateViewModelName = "${pageName}ViewModel.ets";
        String tageViewModelName = templateViewModelName.replace("${pageName}", pageName);
        String ViewModelPath = filePath + File.separator + tageViewModelName;
        // 文件生成
        String s = writeFile("vm/v1/${pageName}Page.ets.vm", context, pagePath, cl);
        String s2 = writeFile("vm/v1/${pageName}ViewModel.ets.vm", context, ViewModelPath, cl);
        // 写入json和枚举
        // 获取src路径
        String srcPath = pagePath.substring(pagePath.indexOf("src"));
        srcPath = srcPath.replace("\\", "/");
        String jsonTemplate = ",\n" +
                "    {\n" +
                "      \"name\": \"${pageName}Page\",\n" +
                "      \"pageSourceFile\": \"${srcPath}\",\n" +
                "      \"buildFunction\": \"${pageName}PageBuilder\",\n" +
                "      \"data\": {\n" +
                "        \"description\": \"${pageNameCN}\"\n" +
                "      }\n" +
                "    }";
        String enumTemplate = ",\n" +
                "  // ${pageNameCN}\n" +
                "  ${pageName}Page = \"${pageName}Page\"";
        jsonTemplate = jsonTemplate.replace("${pageName}", pageName);
        jsonTemplate = jsonTemplate.replace("${srcPath}", srcPath);
        jsonTemplate = jsonTemplate.replace("${pageNameCN}", pageNameCN);

        enumTemplate  = enumTemplate.replace("${pageName}", pageName);
        enumTemplate  = enumTemplate.replace("${pageNameCN}", pageNameCN);

        // 读取 jsonPath 文件，并从后向前查找第二个"}"字符，并把jsonTemplate插入该字符后面，再保存文件
        try {
            // 读取json文件内容
            String jsonContent = new String(Files.readAllBytes(Paths.get(jsonPath)), "UTF-8");
            // 从后向前查找第二个 "}" 字符
            int firstBraceIndex = jsonContent.lastIndexOf("}");
            int secondBraceIndex = jsonContent.lastIndexOf("}", firstBraceIndex - 1);
            if (secondBraceIndex != -1) {
                // 在第二个 "}" 字符后面插入 jsonTemplate
                StringBuilder modifiedContent = new StringBuilder(jsonContent);
                modifiedContent.insert(secondBraceIndex + 1, jsonTemplate);
                // 保存修改后的内容到文件
                Files.write(Paths.get(jsonPath), modifiedContent.toString().getBytes("UTF-8"), StandardOpenOption.WRITE);
                System.out.println("JSON template has been inserted successfully.");
            } else {
                System.out.println("Could not find the second closing brace '}' in the file.");
            }
            // 读取枚举文件内容
            String enumContent = new String(Files.readAllBytes(Paths.get(enumPath)), "UTF-8");
            // 将enumIndex字符串转换成整数型

            int i = Integer.parseInt(enumIndex) - 1;
            int huanhangIndex = enumContent.lastIndexOf("\"", i);
            int huanhangIndexs = enumContent.lastIndexOf("'", i);
            huanhangIndex=huanhangIndex>huanhangIndexs?huanhangIndex:huanhangIndexs;

            StringBuilder modifiedContent2 = new StringBuilder(enumContent);
            modifiedContent2.insert(huanhangIndex + 1, enumTemplate);
            // 保存修改后的内容到文件
            Files.write(Paths.get(enumPath), modifiedContent2.toString().getBytes("UTF-8"), StandardOpenOption.WRITE);
        } catch (IOException ex) {
            Notifications.Bus.notify(new Notification("Print", "写入json或枚举时出现错误"+ex.getMessage(),
                    s + "\n" + s2, NotificationType.WARNING), e.getProject());
        }

        Notifications.Bus.notify(new Notification("Print", "生成结果",
                s + "\n" + s2, NotificationType.INFORMATION), e.getProject());
/*
        File file = new File(filePath);
        try (OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(fileName), StandardCharsets.UTF_8)) {
            if (!file.exists() && !file.mkdirs()) {
                throw new RuntimeException("将要生成的文件已经存在或者是一个目录！");
            }
            VelocityEngine velocityEngine = new VelocityEngine();
            velocityEngine.setProperty(Velocity.RESOURCE_LOADER, "classpath");
            velocityEngine.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
            velocityEngine.setProperty("output.encoding", "UTF-8");
            velocityEngine.setProperty(Velocity.INPUT_ENCODING, "UTF-8");
            velocityEngine.init();
            Template tpl = velocityEngine.getTemplate("vm/v1/" + templateName + ".vm", StandardCharsets.UTF_8.name());
            BufferedWriter sw = new BufferedWriter(out);
            tpl.merge(context, sw);
            sw.flush();
            sw.close();
        } catch (Exception error) {
            Notifications.Bus.notify(new Notification("Print", "生成代码时发生错误！",
                    "错误信息：" + error.getMessage(), NotificationType.INFORMATION), e.getProject());
        }
        Thread.currentThread().setContextClassLoader(oldContextClassLoader);*/
    }

    /**
     * writeFile 通过模板输出到文件
     *
     * @param templateFilePath java.lang.String 模板文件路径+名称
     * @param velocityContext  org.apache.velocity.VelocityContext 模板上下文对象
     * @param targetPath       java.lang.String 输出目标文件路径
     * @param cl               java.lang.ClassLoader 类加载器
     * @return void
     * @author huhaoran
     * @date 2024/7/15
     */
    private static String writeFile(String templateFilePath, VelocityContext velocityContext, String targetPath, ClassLoader cl) {
        ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(cl);
        OutputStreamWriter out = null;
        BufferedWriter sw = null;
        try {
            File file = new File(targetPath);
            if (file.exists()) {
                throw new RuntimeException("将要生成的文件已经存在！");
            }
            // 确保父目录存在
            File parentDir = file.getParentFile();
            if (parentDir != null && !parentDir.exists() && !parentDir.mkdirs()) {
                throw new RuntimeException("创建目标文件的父目录失败！");
            }
            // 创建文件
            if (!file.createNewFile()) {
                throw new RuntimeException("将要生成的文件已经存在或者是一个目录！");
            }
            out = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8);
            VelocityEngine velocityEngine = new VelocityEngine();
            velocityEngine.setProperty(Velocity.RESOURCE_LOADER, "classpath");
            velocityEngine.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
            velocityEngine.setProperty("output.encoding", "UTF-8");
            velocityEngine.setProperty(Velocity.INPUT_ENCODING, "UTF-8");
            velocityEngine.init();
            Template tpl = velocityEngine.getTemplate(templateFilePath, StandardCharsets.UTF_8.name());
            sw = new BufferedWriter(out);
            tpl.merge(velocityContext, sw);
            sw.flush();
        } catch (Exception error) {
            return "从模板" + templateFilePath + "生成文件" + targetPath + "的时候出现错误：" + error.getMessage();
        } finally {
            Thread.currentThread().setContextClassLoader(oldContextClassLoader);
            try {
                if (sw != null) {
                    sw.close();
                }
            } catch (IOException e) {
                return "关闭缓存区的时候发生错误：" + e.getMessage();
            }
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                return "关闭文件输出流的时候发生错误：" + e.getMessage();
            }
        }
        return "成功通过模板" + templateFilePath + "生成目标文件" + targetPath;
    }

    /**
     * areStringsEqual 比较两个字符串是否相同
     *
     * @param str1 java.lang.String
     * @param str2 java.lang.String
     * @return boolean
     * @author huhaoran
     * @date 2024/7/16
     */
    public static boolean areStringsEqual(String str1, String str2) {
        if (str1 == null && str2 == null) {
            return true;
        } else if (str1 != null && str2 != null) {
            return str1.equals(str2);
        } else {
            return false;
        }
    }

    /**
     * showBalloon 在指定组件上弹出一个消息框
     *
     * @param component javax.swing.JComponent
     * @param message   java.lang.String
     * @return void
     * @author huhaoran
     * @date 2024/7/17
     */
    public static void showMessgerOnBalloon(JComponent component, String message) {
        Balloon balloon = JBPopupFactory.getInstance()
                .createHtmlTextBalloonBuilder(message, null, new Color(255, 94, 94, 194), null)
                .setFadeoutTime(3000)
                .createBalloon();

        // 显示在组件上方
        balloon.show(RelativePoint.getSouthOf(component), Balloon.Position.atLeft);
    }

    // 将文件内容转换为 Map<String, List<String>>
    public static Map<String, List<String>> parseFileContent(String filePath) throws IOException {
        String content = new String(Files.readAllBytes(Paths.get(filePath)), "UTF-8");
        // 正则表达式匹配枚举类
        Pattern enumPattern = Pattern.compile(
                "export enum (\\w+)\\s*\\{(.*?)\\}",
                Pattern.DOTALL
        );
        // 正则表达式匹配枚举值
        Pattern valuePattern = Pattern.compile(
                "(\\w+)\\s*=\\s*\".*?\""
        );
        Map<String, List<String>> result = new HashMap<>();
        Matcher enumMatcher = enumPattern.matcher(content);
        while (enumMatcher.find()) {
            String enumName = enumMatcher.group(1);
            String enumBody = enumMatcher.group(2);
            List<String> enumValues = new ArrayList<>();
            // 查找结束大括号的位置
            int endBracePos = content.indexOf('}', enumMatcher.end()-1);
            enumValues.add(String.valueOf(endBracePos));
            Matcher valueMatcher = valuePattern.matcher(enumBody);
            while (valueMatcher.find()) {
                enumValues.add(valueMatcher.group(1));
            }
            result.put(enumName, enumValues);
        }
        return result;
    }

    // 将文件内容转换为 Map<String, List<String>>
    public static Map<String, List<String>> parseFileContentV2(String filePath) throws IOException {
        String content = new String(Files.readAllBytes(Paths.get(filePath)), "UTF-8");

        // 正则表达式匹配注释和枚举类
        Pattern enumPattern = Pattern.compile(
                "(?:(?:/\\*\\*.*?\\*/)|(?://.*?\\n))*\\s*export enum (\\w+)\\s*\\{(.*?)\\}",
                Pattern.DOTALL | Pattern.MULTILINE
        );

        // 正则表达式匹配枚举值
        Pattern valuePattern = Pattern.compile(
                "(\\w+)\\s*=\\s*\".*?\""
        );

        Map<String, List<String>> result = new HashMap<>();
        Matcher enumMatcher = enumPattern.matcher(content);

        while (enumMatcher.find()) {
            String enumBlock = content.substring(0, enumMatcher.start());
            String enumName = enumMatcher.group(1);
            String enumBody = enumMatcher.group(2);
            List<String> enumValues = new ArrayList<>();

            // 查找结束大括号的位置
            int endBracePos = content.indexOf('}', enumMatcher.end());
            enumValues.add(String.valueOf(endBracePos));

            Matcher valueMatcher = valuePattern.matcher(enumBody);
            while (valueMatcher.find()) {
                enumValues.add(valueMatcher.group(1));
            }

            // 提取注释
            String comment = extractComment(enumBlock);
            String key = enumName + "//" + comment;
            result.put(key, enumValues);
        }

        return result;
    }

    // 提取注释内容
    private static String extractComment(String enumBlock) {
        Pattern commentPattern = Pattern.compile("(?:/\\*\\*(.*?)\\*/)|(?://(.*?))\\n", Pattern.DOTALL | Pattern.MULTILINE);
        Matcher commentMatcher = commentPattern.matcher(enumBlock);
        StringBuilder comments = new StringBuilder();

        while (commentMatcher.find()) {
            if (commentMatcher.group(1) != null) {
                comments.append(commentMatcher.group(1).trim()).append(" ");
            } else if (commentMatcher.group(2) != null) {
                comments.append(commentMatcher.group(2).trim()).append(" ");
            }
        }

        return comments.toString().trim();
    }
}
